package com.meter.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;

@Slf4j
public class HexUtils {
    /**
     * 截取字符串数组，返回数组
     * @param str1 字符串数组
     * @param start 开始位
     * @return 字符串数组
     */
    public static String[] strChange(String str1[],  int start){
        int length = str1.length - start;
        String str2[] = new String[length];
        for(int i = start, j = 0; i < str1.length && j < length; i++, j++){
            str2[j] = str1[i];
        }
        return str2;
    }

    /**
     * 根据长度截取数组，返回数组
     * @param str1  字符串数组
     * @param start  开始位
     * @param length  长度
     * @return 字符数组
     */
    public static String[] strChangeByLength(String str1[], int start, int length){
        String str2[] = new String[length];
        int k = start + length;
        for(int i = start, j = 0 ; i < k && j < length; i++, j++){
            str2[j] = str1[i];
        }
        return str2;
    }

    /**
     * 根据开始位和结束位截取数组，返回数组
     * @param str1  字符串数组
     * @param start  开始位
     * @param end  结束位
     * @return 字符数组
     */
    public static String[] strChange(String str1[], int start, int end){
        int length = end - start;
        String str2[] = new String[length];
        for(int i = start, j = 0 ; i <= end && j < length; i++, j++){
            str2[j] = str1[i];
        }
        return str2;
    }

    /**
     * 截取字符串 从第几位开始截取
     * @param str1 字符串数组
     * @param start 开始位
     * @return 字符串
     */
    public static String strChangeStr(String str1[],  int start, boolean spaceFlag){
        StringBuffer str2 = new StringBuffer();
        int k = str1.length;
        for(int i = start; i < k; i++){
            if(i > start){
                str2.append(" ");
            }
            str2.append(str1[i]);
        }
        if(!spaceFlag){
            return str2.toString().replace(" ", "");
        }
        return str2.toString();
    }

    /**
     * 截取字符串 从第几位开始截取，逆向输出
     * @param str1 字符串数组
     * @param start 开始位
     * @return 字符串
     */
    public static String strChangeStrDesc(String str1[],  int start, boolean spaceFlag){
        String result = "";
        int k = str1.length;
        for(int i = start; i < k; i++){
            String str2 = str1[i];
            if(result.equals("")){
                result = str2;
            }else{
                result = str2 + " " + result;
            }
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 根据开始位和长度截取数组，返回字符串
     * @param str1   字符串数组
     * @param start  开始位
     * @param length  长度
     * @return 字符串
     */
    public static String strChangeStrByLength(String str1[], int start, int length, boolean spaceFlag){
        StringBuffer str2 = new StringBuffer();
        int k = start + length;
        for(int i = start; i < k; i++){
            if(i > start){
                str2.append(" ");
            }
            str2.append(str1[i]);
        }
        if(!spaceFlag){
            return str2.toString().replace(" ", "");
        }
        return str2.toString();
    }

    /**
     * 截取字符串 从第几位开始，截取几位，倒叙排列
     * @param str1
     * @param start
     * @param length
     * @return 字符串
     */
    public static String strChangeStrByLengthDesc(String str1[], int start, int length, boolean spaceFlag){
        int k = start + length;
        String result = "";
        for(int i = start; i < k; i++){
            String str2 = str1[i];
            if(result.equals("")){
                result = str2;
            }else{
                result = str2 + " " + result;
            }
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 根据开始为和结束位截取数组，返回字符串
     * @param str1   字符串数组
     * @param start  开始位
     * @param end  结束位
     * @return 字符串
     */
    public static String strChangeStr(String str1[], int start, int end, boolean spaceFlag){
        StringBuffer str2 = new StringBuffer();
        for(int i = start; i <= end; i++){
            if(i > start){
                str2.append(" ");
            }
            str2.append(str1[i]);
        }
        if(!spaceFlag){
            return str2.toString().replace(" ", "");
        }
        return str2.toString();
    }

    /**
     * 根据开始为和结束位截取数组，返回字符串
     * @param str1   字符串数组
     * @param start  开始位
     * @param end  结束位
     * @return 字符串
     */
    public static String strChangeStrDesc(String str1[], int start, int end, boolean spaceFlag){
        String result = "";
        for(int i = start; i <= end; i++){
            String str2 = str1[i];
            if(result.equals("")){
                result = str2;
            }else{
                result = str2 + " " + result;
            }
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 将字符串转成数组格式
     * @param str1  字符串数
     * @param length 间隔长度
     * @return 字符串
     */
    public static String[] strChange(String str1,  int length) {
        int k = str1.length();
        int l = k / length;
        try{
            if(k%length != 0){
                throw new Exception("传入的字符串位数不正确");
            }
        }catch (Exception e){
            log.error("传入的字符串位数不正确！");
        }
        String str2[] = new String[l];
        for(int i = 0; i < l; i++){
            str2[i] = str1.substring(0, length);
            str1 = str1.substring(length);
        }
        return str2;
    }

    /**
     * 将字符串转成数组格式
     * @param str1  字符串数
     * @param length 间隔长度
     * @return 字符串
     */
    public static String[] strChangeDesc(String str1,  int length) {
        int k = str1.length();
        int l = k / length;
        try{
            if(k%length != 0){
                throw new Exception("传入的字符串位数不正确");
            }
        }catch (Exception e){
            log.error("传入的字符串位数不正确！");
        }
        String str2[] = new String[l];
        for(int i = 0; i < l; i++){
            str2[i] = str1.substring(k-length, k);
            str1 = str1.substring(0, k-length);
            k -= length;
        }
        return str2;
    }

    /**
     * 将字符串以数量转化，中间加空格
     * @param str1
     * @param length
     * @return 字符串
     */
    public static String strChangeStr(String str1, int length, boolean spaceFlag) {
        int k = str1.length();
        int l = k / length;
        try{
            if(k%length != 0){
                throw new Exception("传入的字符串位数不正确");
            }
        }catch (Exception e){
            log.error("传入的字符串位数不正确！");
        }
        StringBuffer str2 = new StringBuffer();
        for(int i = 0; i < l ; i++){
            if(i > 0){
                str2.append(" ");
            }
            str2.append(str1.substring(0, length));
            str1 = str1.substring(length);
        }
        if(!spaceFlag){
            return str2.toString().replace(" ", "");
        }
        return str2.toString();
    }

    /**
     * 将字符串以数量转化，中间加空格，并将数据反向返回
     * @param str1
     * @param length
     * @return 字符串
     */
    public static String strChangeStrDesc(String str1, int length, boolean spaceFlag) {
        int k = str1.length();
        int l = k / length;
        try{
            if(k%length != 0){
                throw new Exception("传入的字符串位数不正确");
            }
        }catch (Exception e){
            log.error("传入的字符串位数不正确！");
        }
        StringBuffer str2 = new StringBuffer();
        for(int i = 0; i < l; i++){
            if(i > 0){
                str2.append(" ");
            }
            str2.append(str1.substring(k-length, k));
            str1 = str1.substring(0, k-length);
            k -= length;
        }
        if(!spaceFlag){
            return str2.toString().replace(" ", "");
        }
        return str2.toString();
    }

    /**
     * @Title:hexString2Bytes
     * @Description:16进制字符串转字节数组
     * @param src 16进制字符串
     * @return 字节数组
     * @throws
     */
    public static byte[] hexString2Bytes(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }

    /**
     * 十六进制转2进制字符串数组
     **/
    public static String[] hexStringBinStr(String hexStr, int length) {
        int num = Integer.valueOf(hexStr, 16);
        String str = Integer.toBinaryString(num);
        for(int i = str.length(); i < length; i++){
            str = "0" + str;
        }
        char[] strChar = str.toCharArray();
        String result = "";
        for(int i = 0; i < strChar.length; i++){
            result += strChar[i] + " ";
        }
        return result.split(" ");
    }

    /**
     * 十六进制转2进制字符串
     **/
    public static String hexStringBinStr(String hexStr, int length, boolean spaceFlag) {
        int num = Integer.valueOf(hexStr, 16);
        String str = Integer.toBinaryString(num);
        for(int i = str.length(); i < length; i++){
            str = "0" + str;
        }
        char[] strChar = str.toCharArray();
        String result = "";
        for(int i = 0; i < strChar.length; i++){
            result += strChar[i] + " ";
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 十六进制转2进制字符串数组
     **/
    public static String[] hexStringBinStrDesc(String hexStr, int length) {
        int num = Integer.valueOf(hexStr, 16);
        String str = Integer.toBinaryString(num);
        for(int i = str.length(); i < length; i++){
            str = "0" + str;
        }
        char[] strChar = str.toCharArray();
        String result = "";
        for(int i = 0; i < strChar.length; i++){
            result = strChar[i] + " " + result;
        }
        return result.split(" ");
    }

    /**
     * 十六进制转2进制字符串
     **/
    public static String hexStringBinStrDesc(String hexStr, int length, boolean spaceFlag) {
        int num = Integer.valueOf(hexStr, 16);
        String str = Integer.toBinaryString(num);
        for(int i = str.length(); i < length; i++){
            str = "0" + str;
        }
        char[] strChar = str.toCharArray();
        String result = "";
        for(int i = 0; i < strChar.length; i++){
            result = strChar[i] + " " + result;
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 二进制转十六进制
     * @param binStr
     * @return
     */
    public static String bin2Str(String binStr) {
        StringBuilder sb = new StringBuilder();
        int len = binStr.length();

        for (int i = 0; i < len / 4; i++) {
            //每4个二进制位转换为1个十六进制位
            String temp = binStr.substring(i * 4, (i + 1) * 4);
            int tempInt = Integer.parseInt(temp, 2);
            String tempHex = Integer.toHexString(tempInt).toUpperCase();
            sb.append(tempHex);
        }
        return sb.toString();
    }

    /**
     * 二进制转十进制
     * @param num
     * @return
     */
    public static Integer get10Num(String num){
        return Integer.parseInt(num, 2);
    }

    /**
     * 二进制转十进制
     * @param num
     * @param length
     * @return
     */
    public static String get10NumStr(String num, int length){
        String binStr = String.valueOf(Integer.parseInt(num, 2));
        return StringUtils.matchString(binStr, length);
    }

    /**
     * 十进制转二进制
     * @param num
     * @param length
     * @return
     */
    public static String getBinStr(int num, int length) {
        String binStr = Integer.toBinaryString(num);
        return StringUtils.matchString(binStr, length);
    }

    /**
     * 十六进制转十进制 (无符号)
     * @param num
     * @return
     */
    public static Integer get10HexNum(String num){
        return Integer.parseInt(num, 16);
    }

    /**
     * 十六进制转十进制 (有符号)
     * @param num
     * @return
     */
    public static short getShortHexNum(String num){
        return (short)(Long.valueOf(num, 16) & 0xffff);
    }

    /**
     * 数组每个数值减去固定数，得到返回值数据
     * @param msgs
     * @param fixed
     * @return
     */
    public static String getHexNumByFixed(String[] msgs, String fixed, boolean spaceFlag){
        int fix = HexUtils.get10HexNum(fixed);
        String result = "";
        for(String msg : msgs){
            int value = HexUtils.get10HexNum(msg) - fix;
            String hex = HexUtils.get16HexNum(value);
            result = hex + " " + result;
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 数组每个数值加上固定数，得到返回值数据
     * @param msgs
     * @param fixed
     * @return
     */
    public static String getHexNumerByFixed(String[] msgs, String fixed, boolean spaceFlag){
        int fix = HexUtils.get10HexNum(fixed);
        String result = "";
        for(String msg : msgs){
            int value = get10HexNum(msg) + fix;
            String hex = HexUtils.get16HexNum(value);
            if (hex.length() > 2) {
                hex = hex.substring(2);
            }
            if(result.equals("")) {
                result = hex;
            }else {
                result = hex + " " + result;
            }
        }
        if(!spaceFlag){
            return result.replace(" ", "");
        }
        return result;
    }

    /**
     * 十进制转十六进制
     * @param num
     * @return
     */
    public static String get16HexNum(int num){
        String hex = Integer.toHexString(num).toUpperCase();
        if(hex.length() % 2 != 0){
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 十六进制转float
     * @param num
     * @return
     */
    public static Float getFloatHexNum(String num){
        return Float.intBitsToFloat(new BigInteger(num.trim(), 16).intValue());
    }

    /**
     * float转16进制
     * @param num
     * @return
     */
    public static String getHexFloatNum(Float num){
        String hex = Integer.toHexString(Float.floatToIntBits(num));
        if(hex.length() % 2 != 0){
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 16进制直接转换成为字符串(ASCII码)
     * @param hexStr
     * @return
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            int n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte)(n & 0xFF);
        }
        return new String(bytes);
    }

    /**
     * 字符串转16进制（ASCII）
     * @param str
     * @return
     */
    public static String hexString2Str(String str) {
        char[] chars = str.toCharArray();
        StringBuffer hex = new StringBuffer();
        for(int i = 0; i < chars.length; i++){
            hex.append(Integer.toHexString((int)chars[i]));
        }
        return hex.toString();
    }

    /**
     * 字节数组转float
     * 采用IEEE 754标准
     * @param bytes
     * @return
     */
    public static float bytes2Float(byte[] bytes){
        //获取 字节数组转化成的2进制字符串
        String BinaryStr = bytes2BinaryStr(bytes);
        //符号位S
        Long s = Long.parseLong(BinaryStr.substring(0, 1));
        //指数位E
        Long e = Long.parseLong(BinaryStr.substring(1, 9),2);
        //位数M
        String M = BinaryStr.substring(9);
        float m = 0,a,b;
        for(int i = 0; i < M.length(); i++){
            a = Integer.valueOf(M.charAt(i)+"");
            b = (float) Math.pow(2, i+1);
            m =m + (a/b);
        }
        Float f = (float) ((Math.pow(-1, s)) * (1+m) * (Math.pow(2,(e-127))));
        return f;
    }

    /**
     * 将字节数组转换成2进制字符串
     * @param bytes
     * @return
     */
    public static String bytes2BinaryStr(byte[] bytes){
        StringBuffer binaryStr = new StringBuffer();
        for(int i = 0; i < bytes.length; i++){
            String str = Integer.toBinaryString((bytes[i] & 0xFF) + 0x100).substring(1);
            binaryStr.append(str);
        }
        return binaryStr.toString();
    }

    /**
     * 将字节数组转换成16进制 字符串
     * @param bytes
     * @return
     */
    public static String bytes2HexStr(byte[] bytes){
        StringBuffer binaryStr = new StringBuffer();
        for(int i = 0; i < bytes.length; i++){
            String str = Integer.toBinaryString((bytes[i] & 0xFF) + 0x100).substring(1);
            binaryStr.append(str);
        }
        return HexUtils.bin2Str(binaryStr.toString());
    }

    private static final char[] DIGITS
            = {'0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static String Base64toHex(byte[] data) {
        final StringBuffer sb = new StringBuffer(data.length * 2);
        for (int i = 0; i < data.length; i++) {
            sb.append(DIGITS[(data[i] >>> 4) & 0x0F]);
            sb.append(DIGITS[data[i] & 0x0F]);
        }
        return sb.toString();
    }

    /**
     * hex转日期格式
     * @param hexStr
     * @return
     */
    public static String hexStr2Date(String[] hexStr) {
        String date = "";
        for(int i = 0; i < hexStr.length; i++){
            if(date.equals("")){
                date = get10HexNum(hexStr[i]).toString();
            }else{
                date = date + "-" + get10HexNum(hexStr[i]).toString();
            }
        }
        return date;
    }

    /**
     * hex转日期格式
     * @param hexStr
     * @return
     */
    public static String hex2Date(String[] hexStr) {
        String date = "";
        for(int i = 0; i < hexStr.length; i++){
            if(date.equals("")){
                date = hexStr[i];
            }else{
                date = date + "-" + hexStr[i];
            }
        }
        return date;
    }

    /**
     * hex转时间格式
     * @param hexStr
     * @return
     */
    public static String hexStr2Time(String[] hexStr) {
        String time = "";
        for(int i = 0; i < hexStr.length; i++){
            if(time.equals("")){
                time = get10HexNum(hexStr[i]).toString();
            }else{
                time = time + ":" + get10HexNum(hexStr[i].toString());
            }
        }
        return time;
    }

    /**
     * hex转时间格式
     * @param hexStr
     * @return
     */
    public static String hex2Time(String[] hexStr) {
        String time = "";
        for(int i = 0; i < hexStr.length; i++){
            if(time.equals("")){
                time = hexStr[i];
            }else{
                time = time + ":" + hexStr[i];
            }
        }
        return time;
    }

    /**
     * 字符串倒叙输出
     * @param hexStr
     * @return
     */
    public static Integer hexIntegerDesc(String hexStr){
        String result = "";
        char[] hexs = hexStr.toCharArray();
        for(int i = hexs.length - 1; i >= 0; i--){
            result = result + hexs[i];
        }
        return Integer.parseInt(result);
    }

    /**
     * 数据计算校验和
     * @param msgs
     * @return
     */
    public static String hexCheckStr(String[] msgs){
        int num = 0;
        for(int i = 0; i < msgs.length; i++){
            if(StringUtils.isNotEmpty(msgs[i])) {
                num = num + HexUtils.get10HexNum(msgs[i]);
            }
        }
        String hex = HexUtils.get16HexNum(num);
        if(hex.length() > 2) {
            hex = hex.substring(hex.length() - 2);
        }
        return hex;
    }

    /**
     * 16进制数据按位取反
     * @param msgs
     * @return
     */
    public static String hexCheckStrReverse(String[] msgs){
        int num = 0;
        for(int i = 0; i < msgs.length; i++){
            if(StringUtils.isNotEmpty(msgs[i])) {
                num = num + HexUtils.get10HexNum(msgs[i]);
            }
        }
        String hex = HexUtils.get16HexNum(num);
        if(hex.length() > 2) {
            hex = hex.substring(hex.length() - 2);
        }
        byte[] bytes = HexUtils.hexString2Bytes(hex);
        byte temp;
        for(int i = 0; i<bytes.length; i++) {
            temp = bytes[i];
            bytes[i] = (byte) (~temp);
        }
        String result = HexUtils.bytes2HexStr(bytes);
        return result;
    }

}
